package org.zoomdev.zoom.web.test;

import org.apache.commons.fileupload.FileItem;
import org.zoomdev.zoom.aop.ProxyFactory;
import org.zoomdev.zoom.aop.impl.AsmProxyFactory;
import org.zoomdev.zoom.aop.impl.PartProxyObject;
import org.zoomdev.zoom.common.exceptions.ZoomException;
import org.zoomdev.zoom.common.io.Io;
import org.zoomdev.zoom.common.json.JSON;
import org.zoomdev.zoom.common.utils.MapUtils;
import org.zoomdev.zoom.ioc.Ioc;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;


public class MockUtils {
    static ProxyFactory factory = new AsmProxyFactory();

    static class FileItemPart{
        private final File file;

        FileItemPart(File file) {
            this.file = file;
        }

        public byte[] get(){
            try {
                return Io.readBytes(file);
            } catch (IOException e) {
                throw new ZoomException(e);
            }
        }
    }

    public static FileItem fileItem(File file) {
        return factory.createObject(FileItem.class,new PartProxyObject(new FileItemPart(file)));
    }


    public static FilterChain filterChain() {
        return (servletRequest, servletResponse) -> {

        };
    }

    public static FilterConfig filterConfig(Map<String, String> param) {
        return new FilterConfig() {
            @Override
            public String getFilterName() {
                return "filterName";
            }

            @Override
            public ServletContext getServletContext() {
                return null;
            }

            @Override
            public String getInitParameter(String s) {
                return param.get(s);
            }

            @Override
            public Enumeration<String> getInitParameterNames() {

                Iterator<String> it = param.keySet().iterator();
                return new Enumeration<String>() {
                    @Override
                    public boolean hasMoreElements() {
                        return it.hasNext();
                    }

                    @Override
                    public String nextElement() {
                        return it.next();
                    }
                };
            }
        };
    }

    public static HttpServletRequest get(String servletPath) {
        return factory.createObject(HttpServletRequest.class, new PartProxyObject(new HttpServletRequestImpl(servletPath, "GET")));
    }

    /**
     * 模拟一次表单
     *
     * @param servletPath
     * @return
     */
    public static RequestBuilder request(String servletPath) {
        return new RequestBuilder(servletPath);
    }

    public static MockResponse response() {
        return factory.createObject(MockResponse.class, new PartProxyObject(new HttpServletResponseImpl()));
    }

    public static MockServletOutputStream outputStream() {
        return factory.createObject(MockServletOutputStream.class, new PartProxyObject(new OutputStreamImpl()));
    }


    public static ServletInputStream inputStream(byte[] content) {
        return factory.createObject(ServletInputStream.class, new PartProxyObject(new InputStreamImpl(content)));
    }

    public static MockWebService web(Ioc ioc) {
        return new MockWebService(ioc);
    }

    public static class RequestBuilder {

        private final String url;
        private String method;

        private Map<String, String> form;

        private Map<String, String> header;

        private byte[] body;

        private String contentType;

        public RequestBuilder(String url) {
            this.url = url;
        }

        public RequestBuilder json(Object data) {
            this.contentType = "application/json";
            this.body = JSON.stringify(data).getBytes(StandardCharsets.UTF_8);
            return method("POST");
        }

        public RequestBuilder form(Map<String, String> data) {
            this.form = data;
            this.contentType = "application/x-www-form-urlencoded";
            return method("POST");
        }

        public RequestBuilder method(String method) {
            this.method = method;
            return this;
        }

        public RequestBuilder header(String key, String value) {
            if (header == null) {
                header = new HashMap<>();
            }
            header.put(key, value);
            return this;
        }

        public HttpServletRequest build() {
            try {
                HttpServletRequestImpl request = new HttpServletRequestImpl(url, method);
                request.setContentType(contentType);
                request.setParameters(form);
                if (header != null) {
                    for (Map.Entry<String, String> entry : header.entrySet()) {
                        request.setHeader(entry.getKey(), entry.getValue());
                    }

                }

                if (body == null) {
                    if (form != null) {
                        body = MapUtils.toQueryString(form).getBytes(StandardCharsets.UTF_8);
                    }
                }
                request.setContent(body);
                return factory.createObject(HttpServletRequest.class, new PartProxyObject(request));
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }


    }


}
